include // Voronoi from https://github.com/felipesanches/OpenSCAD_Voronoi_Generator use use box_diameter = 86; //mm box_thickness = 28; //mm box_rounding = 10;//mm wall_thickness = 3;//mm register_thickness = 1; //mm register_depth = 1; //mm register_tolerance = 0.1;//mm register_friction_bars = 6; friction_bar_thickness=0.75;//mm friction_bar_length=1;//mm hinge_length = 60; //mm hinge_width = 30; //mm hinge_thickness = 0.6; //mm 3 0.2mm layers hinge_rounding = 15;//mm bottom_voronoi_seed = 100; top_voronoi_seed = 1541; voronoi_count = 100; voronoi_thickness=1; voronoi_rounding=0.5; voronoi_texture_thickness = 1.5; //mm voronoi_texture = false; text_texture_thickness = 1.5; //mm text_texture = true; binary_texture_thickness = 1.5; //mm binary_angle_pad = 0.0; // fraction binary_line_pad = 0.0; // fraction binary_width = 4; binary_offset = 2; binary_data = ["01111010"]; //["01010010", "01000001", "00110001", "00110111", "01101000", "00110100", "00110101", "01101101", "00110100", "00110000", "00101110", "00110000", "00110100", "00110000", "00111001", "01110011","01000100", "01100101", "01100011", "11100010", "10001000", "10010010", "00110010", "00111001", "11000010", "10110000", "00110000", "11100010", "10000000", "10110010", "00110010", "00111000", "00101110", "00110001", "00110001", "00111000", "11100010", "10000000", "10110011"]; binary_read_start_indicator_radius = 1; binary_texture = true; textured_interior = true; interior_texture = "cubes"; // See https://github.com/revarbat/BOSL2/wiki/skin.scad#function-texture for available textures interior_texture_depth = 0.4; // multiplier interior_texture_size = [10,10]; resolution = 200; // must be pair // code hinge_length_adjusted = box_diameter+hinge_length+hinge_width; module voronoi_polygon(border, n=30, thickness=1.7, round=1.0, edging=3.0, seed=undef) { // bounding box only_x = [ for (point = border) point[0] ]; only_y = [ for (point = border) point[1] ]; min_x = min(only_x); min_y = min(only_y); max_x = max(only_x); max_y = max(only_y); // echo([[min_x,min_y],[max_x,max_y]]); // compute sizes, centers and scaling size_x = max_x - min_x; size_y = max_y - min_y; L = max(size_x, size_y); scale_voro = [ size_x / L, size_y / L ]; center_poly = [(min_x + max_x) / 2, (min_y + max_y) / 2]; // subtract Voronoi pattern from the border polygon (disabled) difference() { //polygon(border); translate(center_poly) scale(scale_voro) random_voronoi(n = n, nuclei = false, L = L, thickness = thickness, round = round, min = 0, max = L, seed = seed, center = true); } // add the border edge if required if (edging) { difference() { polygon(border); offset(delta = -edging) polygon(border); } } } module register(bottom_part=true){ applied_tolerance = bottom_part ? register_tolerance : -register_tolerance; translate([0,0,box_thickness/4]) tube(h=register_depth*2, od=box_diameter-wall_thickness+register_thickness+applied_tolerance, id=box_diameter-wall_thickness-register_thickness-applied_tolerance,$fn= resolution); for (i = [0 : 1 : register_friction_bars]) { angle_register_friction = 360*i/register_friction_bars; computed_bar_radius = box_diameter/2-wall_thickness/2; computed_bar_length = friction_bar_length+applied_tolerance/2; computed_bar_radius_min_length = computed_bar_radius-computed_bar_length; translate([sin(angle_register_friction)*computed_bar_radius, cos(angle_register_friction)*computed_bar_radius, 0 ]) translate([0,0,box_thickness/4-register_depth]) rotate([0,0,-angle_register_friction]) cube([friction_bar_thickness+applied_tolerance/2,computed_bar_length,register_depth*2]); translate([sin(angle_register_friction)*computed_bar_radius_min_length, cos(angle_register_friction)*computed_bar_radius_min_length, 0 ]) translate([0,0,box_thickness/4-register_depth]) rotate([0,0,-angle_register_friction]) cube([friction_bar_thickness+applied_tolerance/2,computed_bar_length,register_depth*2]); } } module box_half(bottom_part=true,voronoi_seed=1000){ difference(){ cyl(d=box_diameter, l=box_thickness/2, rounding1=box_rounding,$fn= resolution); if (textured_interior){ translate([0,0,wall_thickness/2]) cyl(d=box_diameter-wall_thickness*2, l=box_thickness/2-wall_thickness, rounding1=box_rounding-wall_thickness, texture=interior_texture, tex_size=interior_texture_size,tex_scale=interior_texture_depth,$fn= resolution); } else { translate([0,0,wall_thickness/2]) cyl(d=box_diameter-wall_thickness*2, l=box_thickness/2-wall_thickness, rounding1=box_rounding-wall_thickness,$fn= resolution); } if (bottom_part){ register(bottom_part); } potential_voronoi_texture(voronoi_seed); if (bottom_part){ potential_texts(); } if (!bottom_part){ potential_binary(); } } if (!bottom_part){ register(bottom_part); } } external_texture_radius=box_diameter/2-box_rounding-wall_thickness; external_surface_offset =[0,0,-box_thickness/4]; module potential_voronoi_texture(voronoi_seed=1000){ if (voronoi_texture){ border2 = [[box_diameter/2,box_diameter/2], [-box_diameter/2,box_diameter/2], [-box_diameter/2,-box_diameter/2], [box_diameter/2,-box_diameter/2]]; translate(external_surface_offset) intersection(){ linear_extrude(height = voronoi_texture_thickness) voronoi_polygon(border2,n=voronoi_count, thickness=voronoi_thickness, round=voronoi_rounding, edging=0, seed=voronoi_seed); translate([0,0,wall_thickness/2]) cylinder(h=wall_thickness,r=external_texture_radius,center=true,$fn= resolution); } } } module revolve_text(radius, chars) { PI = 3.14159; circumference = 2 * PI * radius; chars_len = len(chars); font_size = circumference / chars_len; step_angle = 360 / chars_len; for(i = [0 : chars_len - 1]) { rotate([0,180,i * step_angle]) translate([0, radius + font_size / 2, 0]) text( chars[i], font = "Noto Sans Mono:style=bold", size = font_size, valign = "center", halign = "center" ); } } module potential_text(radius,text_string){ translate(external_surface_offset) linear_extrude(height = text_texture_thickness) revolve_text(radius, text_string); } module potential_texts(){ if (text_texture){ potential_text(external_texture_radius-6,"Ad astra per aspera. "); potential_text(external_texture_radius-8*2,"OnTake. 2023. "); } } module sector(radius, angles, fn = 24) { r = radius / cos(180 / fn); step = -360 / fn; points = concat([[0, 0]], [for(a = [angles[0] : step : angles[1] - 360]) [r * cos(a), r * sin(a)] ], [[r * cos(angles[1]), r * sin(angles[1])]] ); difference() { circle(radius, $fn = fn); polygon(points); } } module arc(radius, angles, width = 1) { difference() { sector(radius + width, angles,fn=resolution/2); sector(radius, angles,fn=resolution/2); } } module binary_arcs(radius,binary,width){ translate([(radius+width+binary_read_start_indicator_radius),0,0]) circle(r=binary_read_start_indicator_radius,$fn=resolution); line_count=len(binary); for(line_index = [0 : line_count - 1]) { bin_count = len(binary[line_index]); angle_inc = 360/bin_count; for(i = [0 : bin_count - 1]) { if (binary[line_index][i] == "1"){ arc(radius-line_index*width+width*binary_line_pad, [i*angle_inc,(i+(1-binary_angle_pad))*angle_inc], width*(1-binary_line_pad)); } } } } module potential_binary(){ if (binary_texture){ translate(external_surface_offset) linear_extrude(height = binary_texture_thickness) binary_arcs(external_texture_radius-binary_width-binary_offset,binary_data,binary_width); } } box_half(true,bottom_voronoi_seed); other_half_offset = [hinge_length_adjusted-hinge_width,0,0]; translate(other_half_offset) box_half(false,top_voronoi_seed); difference(){ translate([-hinge_width/2,-hinge_width/2,-box_thickness/4]) cuboid([hinge_length_adjusted,hinge_width,hinge_thickness],rounding=hinge_rounding, edges=["Z"],anchor=BOTTOM+FRONT+LEFT); potential_voronoi_texture(bottom_voronoi_seed); translate(other_half_offset) potential_voronoi_texture(top_voronoi_seed); potential_texts(); translate(other_half_offset) potential_binary(); }